package com.vr.xuecheng.auth.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vr.xuecheng.auth.dto.AuthParamsDTO;
import com.vr.xuecheng.auth.dto.LoginUserDTO;
import com.vr.xuecheng.auth.dto.WxResultOfGetAccessToken;
import com.vr.xuecheng.auth.entity.User;
import com.vr.xuecheng.auth.entity.UserRole;
import com.vr.xuecheng.auth.mapper.UserMapper;
import com.vr.xuecheng.auth.service.IAuthService;
import com.vr.xuecheng.auth.service.IUserRoleService;
import com.vr.xuecheng.auth.service.IWxAuthService;
import com.vr.xuecheng.base.exception.XueChengPlusException;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.UUID;

/**
 * @author hzh
 * @date 2025/03/30
 * 授权码模式，微信的实现
 */
@Log4j2
@Service("wx_authService")
@RequiredArgsConstructor
public class WxAuthServiceImpl implements IAuthService, IWxAuthService {
    @Value("${wx.appid}")
    private String appid;
    @Value("${wx.secret}")
    private String secret;
    private final RestTemplate restTemplate;
    private final UserMapper userMapper;
    private final IUserRoleService userRoleService;
    @Lazy
    @Autowired
    private IWxAuthService wxAuthService;

    @Override
    public LoginUserDTO execute(AuthParamsDTO authParamsDTO) {
        String username = authParamsDTO.getUsername();
        if (username == null) {
            XueChengPlusException.cast("账号信息完整");
        }
        User wxUser = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, username)
        );
        if (wxUser == null) {
            XueChengPlusException.cast("用户不存在");
        }
        return BeanUtil.toBean(wxUser, LoginUserDTO.class);
    }

    @Override
    public LoginUserDTO wxAuth(String code) {
        // 1、通过授权码获取令牌
        WxResultOfGetAccessToken wxResultOfGetAccessToken = this.getAccessToken(code);
        // 2、通过令牌获取用户信息
        Map<String, String> userInfo = this.getUserInfo(wxResultOfGetAccessToken);
        // 3、保存或者更新用户信息到本项目数据库
        return wxAuthService.updateOrSave(userInfo);
    }

    @Override
    @Transactional
    public LoginUserDTO updateOrSave(Map<String, String> userInfo) {
        // 判断用户是否存在
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getWxUnionid, userInfo.get("unionid"))
        );
        if (user != null) {
            // 更新操作
            User waitUpdate = BeanUtil.toBean(user, User.class);
            waitUpdate
                    .setNickname(userInfo.get("nickname"))
                    .setSex(String.valueOf(userInfo.get("sex")))
                    .setUserpic(userInfo.get("headimgurl"));
            userMapper.updateById(waitUpdate);
            return BeanUtil.toBean(waitUpdate, LoginUserDTO.class);
        } else {
            // 新增操作
            String id = UUID.randomUUID().toString();
            String unionid = userInfo.get("unionid");
            String nickname = userInfo.get("nickname");
            User waitAddUser = User.builder()
                    .id(id)
                    .username(unionid)
                    .password(unionid)
                    .wxUnionid(unionid)
                    .nickname(nickname)
                    .name(nickname)
                    .utype("101001")
                    .sex(String.valueOf(userInfo.get("sex")))
                    .status("1")
                    .userpic(userInfo.get("headimgurl"))
                    .createTime(LocalDateTime.now())
                    .updateTime(LocalDateTime.now())
                    .build();
            userMapper.insert(waitAddUser);
            // 分配角色
            userRoleService.save(UserRole.builder()
                    .id(UUID.randomUUID().toString())
                    .userId(id)
                    // 学生角色
                    .roleId("17")
                    .build());
            return BeanUtil.toBean(waitAddUser, LoginUserDTO.class);
        }
    }


    private WxResultOfGetAccessToken getAccessToken(String code) {
        String urlTemplate = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
        String url = String.format(urlTemplate, appid, secret, code);
        String result = restTemplate.getForObject(url, String.class);
        return JSON.parseObject(result, WxResultOfGetAccessToken.class);
    }

    private Map<String, String> getUserInfo(WxResultOfGetAccessToken wxResultOfGetAccessToken) {
        String urlTemplate = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN";
        String url = String.format(urlTemplate, wxResultOfGetAccessToken.getAccess_token(), wxResultOfGetAccessToken.getOpenid());
        String result = restTemplate.getForObject(url, String.class);
        return JSON.parseObject(result, Map.class);
    }
}
